/**
 *  excel summary 构建类
 *
 * created by nongzhizhong on 2023/02/13
 */
const path = require('path');
const fs = require('fs-extra');
const BaseExcel = require('../../../adapter/excel');

const levelKey = {
  mandatory: '强制',
  required: '要求/必要/强烈推荐',
  advisory: '建议/推荐',
};
const levelDesc = {
  mandatory: '软件编程中强制要求遵循',
  required: '软件编程中若不遵循需满足一定条件',
  advisory: '软件编程中推荐参照执行',
};
const levelColor = {
  mandatory: 'ca3e36',
  required: 'fdbb36',
  advisory: '4dd5b3',
};

class SummaryExcel extends BaseExcel {
  constructor() {
    super('rocket');
    this.mergeByCells = [];
    this.fontBoldByCells = [];
    this.borderBoldByCells = [];
    this.borderBoldOnlyBottomByCells = [];
    this.fillBgColorByCells = {
      mandatory: [],
      required: [],
      advisory: [],
    };
    this.contextAlignmentOfCells = {
      left: [],
      center: [],
      right: [],
    };
    this.lastRowNumber = 0;
  }

  async generate(data, output = path.join('summary.xlsx')) {
    this.addSheet('静态分析总览');
    this.pojectVersionInfo(data);
    await this.defectStatistics(data);
    this.checkResultStatistics(data);
    this.recheckResultStatistics(data);
    await this.defectTypeAnalysis(data);
    await this.defectFileAnalysis(data);
    this.defectRiskLevel(data);
    this.defectOverview(data);
    this.renderStyle();
    // 导出文件
    return this.writeFile(output);
  }

  // 设置样式
  renderStyle() {
    const defaultFont = { name: 'Arial', size: 14, color: { argb: '333333' } };
    this.lastSheet.properties.defaultRowHeight = 30;
    this.lastSheet.getRow(1).height = 40;
    // 设置默认字体
    [1, 2, 3, 4, 5, 6, 7].forEach((number) => {
      this.lastSheet.getColumn(number).font = defaultFont;
    });

    this.lastSheet.properties.defaultColWidth = 15;
    [2, 3, 4, 5, 6].forEach((number) => {
      this.lastSheet.getColumn(number).width = 20;
    });
    // 加粗字体
    this.fontBoldByCells.forEach((position) => {
      this.setCell(position, {
        font: {
          ...defaultFont,
          color: { argb: '000000' },
          bold: true,
        },
      });
    });
    // 合并单元格
    this.mergeByCells.forEach((position) => {
      this.lastSheet.mergeCells(position);
    });
    // 填充颜色
    Object.keys(this.fillBgColorByCells).forEach((key) => {
      this.fillBgColorByCells[key].forEach((position) => {
        this.setCell(position, {
          fill: {
            type: 'pattern',
            pattern: 'solid',
            fgColor: { argb: levelColor[key] },
          },
          border: {
            right: { style: 'medium' },
            bottom: { style: 'medium', color: { argb: 'FFFFFF' } },
          },
          font: {
            ...defaultFont,
            color: { argb: 'FFFFFF' },
          },
        });
      });
    });
    // 边框加粗
    [...this.borderBoldByCells, ...this.borderBoldOnlyBottomByCells].forEach((position) => {
      let border = {
        top: { style: 'medium' },
        left: { style: 'medium' },
        bottom: { style: 'medium' },
        right: { style: 'medium' },
      };
      if (this.borderBoldOnlyBottomByCells.includes(position)) {
        border = { bottom: { style: 'medium' } };
        if (position.indexOf('G') !== -1) {
          border.right = { style: 'medium' };
        }
      }
      this.setCell(position, { border });
    });
    // 对齐方式
    Object.keys(this.contextAlignmentOfCells).forEach((key) => {
      this.contextAlignmentOfCells[key].forEach((position) => {
        this.setCell(position, {
          alignment: {
            vertical: 'middle',
            horizontal: key,
            wrapText: true,
          },
        });
      });
    });
  }

  /**
   * 处理项目信息,包含文件标题
   */
  pojectVersionInfo(data) {
    const sheet = this.lastSheet;
    sheet.getCell('A1').value = data.reportName;
    sheet.getRow(1).height = 58;
    sheet.getCell('A2').value = `日期:${data.reportTime.substr(0, 10)}`;
    sheet.getCell('A3').value = '项目名称';
    sheet.getCell('C3').value = data.projectName;
    sheet.getCell('A4').value = '版本号';
    sheet.getCell('C4').value = data.versionName;
    sheet.getCell('A5').value = '测试概况\n(测试对象统计)';
    sheet.getCell('C5').value = '代码行数';
    sheet.getCell('D5').value = '文件';
    sheet.getCell('E5').value = '缺陷总数';
    sheet.getCell('F5').value = '缺陷密度';
    sheet.getCell('C6').value = data.numberOfLines;
    sheet.getCell('D6').value = data.fileCount;
    sheet.getCell('E6').value = data.defectsCount;
    sheet.getCell('F6').value = data.kloc;

    // 样式
    this.contextAlignmentOfCells.right.push(...['A2']);
    this.contextAlignmentOfCells.left.push(...['C3', 'C4']);
    this.fontBoldByCells.push(...['A1', 'A3', 'A4', 'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5']);
    for (let i = 3; i <= 6; i += 1) {
      ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((key) => {
        this.borderBoldByCells.push(`${key}${i}`);
      });
    }

    this.mergeByCells.push(...[
      'A1:G1', 'A2:G2',
      'A3:B3', 'C3:G3',
      'A4:B4', 'C4:G4',
      'A5:B6', 'F5:G5',
      'F6:G6',
    ]);
    this.lastRowNumber = 6;
  }

  /**
   * 缺陷统计
   */
  async defectStatistics(data) {
    this.lastRowNumber += 2;
    let position = `A${this.lastRowNumber}`;
    const sheet = this.lastSheet;
    sheet.getCell(position).value = '缺陷统计';
    this.contextAlignmentOfCells.left.push(position);
    position = `${position}:B${this.lastRowNumber}`;
    this.mergeByCells.push(position);
    this.fontBoldByCells.push(position);
    // 设置缺陷等级统计内容数据
    ['header', ...Object.keys(levelKey)].forEach((key) => {
      this.lastRowNumber += 1;
      if (key === 'header') {
        for (let i = this.lastRowNumber; i <= this.lastRowNumber + 3; i += 1) {
          ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((key) => {
            const position = `${key}${i}`;
            this.borderBoldByCells.push(position);
            this.contextAlignmentOfCells.left.push(position);
          });
          this.mergeByCells.push(...[`A${i}:C${i}`, `D${i}:G${i}`]);
        }
        position = `A${this.lastRowNumber}`;
        this.fontBoldByCells.push(position);
        sheet.getCell(position).value = '缺陷等级';
        position = `D${this.lastRowNumber}`;
        sheet.getCell(`D${this.lastRowNumber}`).value = '数量';
        return;
      }
      position = `A${this.lastRowNumber}`;
      sheet.getCell(position).value = levelKey[key];
      this.fontBoldByCells.push(position);
      position = `D${this.lastRowNumber}`;
      sheet.getCell(position).value = data[key];
    });
    this.lastRowNumber += 1;
    const pieImage = await fs.readFile(data.pieImage);
    position = `A${this.lastRowNumber}:G${this.lastRowNumber}`;
    this.addImageToCell(position, pieImage, 'png');
    sheet.getRow(this.lastRowNumber).height = 400;
    this.mergeByCells.push(position);
    this.lastRowNumber += 1;
  }

  /**
   * 规范检测结果统计
   */
  checkResultStatistics(data) {
    this.lastRowNumber += 1;
    const sheet = this.lastSheet;
    let position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '规范检测结果统计';
    this.fontBoldByCells.push(position);
    position = `${position}:G${this.lastRowNumber}`;
    this.mergeByCells.push(position);
    this.contextAlignmentOfCells.left.push(position);
    ['header', ...data.ruleSetMap].forEach((item) => {
      this.lastRowNumber += 1;
      ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((key) => {
        const position = `${key}${this.lastRowNumber}`;
        this.borderBoldByCells.push(position);
      });
      this.mergeByCells.push(...[`B${this.lastRowNumber}:D${this.lastRowNumber}`, `F${this.lastRowNumber}:G${this.lastRowNumber}`]);
      if (item === 'header') {
        sheet.getCell(`A${this.lastRowNumber}`).value = '序号';
        sheet.getCell(`B${this.lastRowNumber}`).value = '规范';
        sheet.getCell(`E${this.lastRowNumber}`).value = '包含的准则条目';
        sheet.getCell(`F${this.lastRowNumber}`).value = '检测的缺陷数量';
        this.fontBoldByCells.push(...[`A${this.lastRowNumber}`, `B${this.lastRowNumber}`, `E${this.lastRowNumber}`, `F${this.lastRowNumber}`]);
        return;
      }
      sheet.getCell(`A${this.lastRowNumber}`).value = item.index;
      sheet.getCell(`B${this.lastRowNumber}`).value = item.ruleSetName;
      sheet.getCell(`E${this.lastRowNumber}`).value = item.ruleCount;
      sheet.getCell(`F${this.lastRowNumber}`).value = item.defectCount;
    });
    this.lastRowNumber += 1;
  }

  /**
   *检测结果复核统计
   */
  recheckResultStatistics(data) {
    const sheet = this.lastSheet;
    this.lastRowNumber += 1;
    const position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '检测结果复核统计';
    this.fontBoldByCells.push(position);
    this.contextAlignmentOfCells.left.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);
    ['header', ...data.levelStatusMap].forEach((item) => {
      this.lastRowNumber += 1;
      ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((key) => {
        const position = `${key}${this.lastRowNumber}`;
        this.borderBoldByCells.push(position);
      });
      this.mergeByCells.push(...[`A${this.lastRowNumber}:B${this.lastRowNumber}`]);
      if (item === 'header') {
        sheet.getCell(`A${this.lastRowNumber}`).value = '缺陷级别';
        sheet.getCell(`C${this.lastRowNumber}`).value = '待修改';
        sheet.getCell(`D${this.lastRowNumber}`).value = '已修改';
        sheet.getCell(`E${this.lastRowNumber}`).value = '已说明';
        sheet.getCell(`F${this.lastRowNumber}`).value = '忽略';
        sheet.getCell(`G${this.lastRowNumber}`).value = '误报';
        this.fontBoldByCells.push(...[`A${this.lastRowNumber}`, `C${this.lastRowNumber}`, `D${this.lastRowNumber}`, `E${this.lastRowNumber}`, `F${this.lastRowNumber}`, `G${this.lastRowNumber}`]);
        return;
      }
      sheet.getCell(`A${this.lastRowNumber}`).value = item.level;
      sheet.getCell(`C${this.lastRowNumber}`).value = item.status_0;
      sheet.getCell(`D${this.lastRowNumber}`).value = item.status_1;
      sheet.getCell(`E${this.lastRowNumber}`).value = item.status_4;
      sheet.getCell(`F${this.lastRowNumber}`).value = item.status_2;
      sheet.getCell(`G${this.lastRowNumber}`).value = item.status_3;
      this.fontBoldByCells.push(`A${this.lastRowNumber}`);
    });
    this.lastRowNumber += 1;
  }

  /**
   *缺陷类型分析 Top 10
   */
  async defectTypeAnalysis(data) {
    this.lastRowNumber += 1;
    const sheet = this.lastSheet;
    let position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '缺陷类型分析（TOP 10）';
    this.fontBoldByCells.push(position);
    this.contextAlignmentOfCells.left.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);

    this.lastRowNumber += 1;
    position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = `项目${data.projectName}版本${data.versionName}的缺陷类型分析，如表1与图1所示（前10名）：`;
    this.contextAlignmentOfCells.left.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);

    this.lastRowNumber += 1;
    position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '表1: 缺陷类型分析（TOP 10）';
    this.fontBoldByCells.push(position);
    this.contextAlignmentOfCells.center.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);
    // 表格
    ['header', ...data.rulesTop10].forEach((item) => {
      this.lastRowNumber += 1;
      ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((key) => {
        const position = `${key}${this.lastRowNumber}`;
        this.borderBoldByCells.push(position);
      });
      this.mergeByCells.push(...[`B${this.lastRowNumber}:C${this.lastRowNumber}`, `D${this.lastRowNumber}:E${this.lastRowNumber}`, `F${this.lastRowNumber}:G${this.lastRowNumber}`]);
      if (item === 'header') {
        sheet.getCell(`A${this.lastRowNumber}`).value = '序号';
        sheet.getCell(`B${this.lastRowNumber}`).value = '规则信息';
        sheet.getCell(`D${this.lastRowNumber}`).value = '缺陷类型';
        sheet.getCell(`F${this.lastRowNumber}`).value = '缺陷数量';
        this.fontBoldByCells.push(...[`A${this.lastRowNumber}`, `B${this.lastRowNumber}`, `D${this.lastRowNumber}`, `F${this.lastRowNumber}`]);
        return;
      }

      sheet.getCell(`A${this.lastRowNumber}`).value = item.index;
      sheet.getCell(`B${this.lastRowNumber}`).value = `${item.ruleSet}\n${item.ruleCode}`;
      sheet.getCell(`D${this.lastRowNumber}`).value = item.name;
      sheet.getCell(`F${this.lastRowNumber}`).value = item.total;
      sheet.getRow(this.lastRowNumber).height = 60;
      this.contextAlignmentOfCells.left.push(...[`A${this.lastRowNumber}`, `B${this.lastRowNumber}`, `D${this.lastRowNumber}`, `F${this.lastRowNumber}`]);
    });
    this.lastRowNumber += 1;
    const rulesDistributionImage = await fs.readFile(data.rulesDistributionImage);
    position = `A${this.lastRowNumber}:G${this.lastRowNumber}`;
    this.addImageToCell(position, rulesDistributionImage, 'png');
    sheet.getRow(this.lastRowNumber).height = 250;
    this.mergeByCells.push(position);
    this.lastRowNumber += 1;
  }

  /**
   * 缺陷文件分析 Top 10
   */
  async defectFileAnalysis(data) {
    const sheet = this.lastSheet;
    this.lastRowNumber += 1;
    let position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '缺陷文件分析（TOP 10）';
    this.fontBoldByCells.push(position);
    this.contextAlignmentOfCells.left.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);

    this.lastRowNumber += 1;
    position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = `项目${data.projectName}版本${data.versionName}的缺陷文件分析，如表2与图2所示（前10名）：`;
    this.contextAlignmentOfCells.left.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);

    this.lastRowNumber += 1;
    position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '表2: 缺陷文件分析（TOP 10）';
    this.fontBoldByCells.push(position);
    this.contextAlignmentOfCells.center.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);
    // 表格
    ['header', ...data.filesTop10].forEach((item) => {
      this.lastRowNumber += 1;
      ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((key) => {
        const position = `${key}${this.lastRowNumber}`;
        this.borderBoldByCells.push(position);
      });
      this.mergeByCells.push(...[`B${this.lastRowNumber}:E${this.lastRowNumber}`, `F${this.lastRowNumber}:G${this.lastRowNumber}`]);
      if (item === 'header') {
        sheet.getCell(`A${this.lastRowNumber}`).value = '序号';
        sheet.getCell(`B${this.lastRowNumber}`).value = '文件';
        sheet.getCell(`F${this.lastRowNumber}`).value = '缺陷数量';
        this.fontBoldByCells.push(...[`A${this.lastRowNumber}`, `B${this.lastRowNumber}`, `F${this.lastRowNumber}`]);
        return;
      }

      sheet.getCell(`A${this.lastRowNumber}`).value = item.index;
      sheet.getCell(`B${this.lastRowNumber}`).value = item.fileName;
      sheet.getCell(`F${this.lastRowNumber}`).value = item.total;
      sheet.getRow(this.lastRowNumber).height = 30;
      this.contextAlignmentOfCells.left.push(...[`A${this.lastRowNumber}`, `B${this.lastRowNumber}`, `F${this.lastRowNumber}`]);
    });
    this.lastRowNumber += 1;
    const filesDistributionImage = await fs.readFile(data.filesDistributionImage);
    position = `A${this.lastRowNumber}:G${this.lastRowNumber}`;
    this.addImageToCell(position, filesDistributionImage, 'png');
    sheet.getRow(this.lastRowNumber).height = 250;
    this.mergeByCells.push(position);
    this.lastRowNumber += 1;
  }

  /**
   * 缺陷风险等级
   */
  defectRiskLevel() {
    const sheet = this.lastSheet;
    this.lastRowNumber += 1;
    let position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '风险等级';
    this.fontBoldByCells.push(position);
    this.contextAlignmentOfCells.left.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);

    this.lastRowNumber += 1;
    position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '缺陷风险严重等级描述，如表3所示：';
    this.contextAlignmentOfCells.left.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);

    this.lastRowNumber += 1;
    position = `A${this.lastRowNumber}`;
    sheet.getCell(position).value = '表3: 风险等级描述';
    this.fontBoldByCells.push(position);
    this.contextAlignmentOfCells.center.push(position);
    this.mergeByCells.push(`${position}:G${this.lastRowNumber}`);
    ['header', ...Object.keys(levelKey)].forEach((key) => {
      this.lastRowNumber += 1;
      ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((col) => {
        const position = `${col}${this.lastRowNumber}`;
        this.borderBoldByCells.push(position);
        this.contextAlignmentOfCells.left.push(position);
      });
      this.mergeByCells.push(...[`A${this.lastRowNumber}:C${this.lastRowNumber}`, `D${this.lastRowNumber}:G${this.lastRowNumber}`]);
      if (key === 'header') {
        position = `A${this.lastRowNumber}`;
        this.fontBoldByCells.push(position);
        sheet.getCell(position).value = '缺陷严重等级';
        position = `D${this.lastRowNumber}`;
        sheet.getCell(`D${this.lastRowNumber}`).value = '描述';
        this.fontBoldByCells.push(position);
        return;
      }
      position = `A${this.lastRowNumber}`;
      sheet.getCell(position).value = levelKey[key];
      this.fontBoldByCells.push(position);
      position = `D${this.lastRowNumber}`;
      sheet.getCell(position).value = levelDesc[key];
    });
    this.lastRowNumber += 1;
  }

  /**
  * 缺陷总览
  */
  defectOverview(data) {
    const sheet = this.lastSheet;
    data.allRulesBySet.forEach((ruleSet) => {
      this.lastRowNumber += 1;
      // 表个备注
      let position = `A${this.lastRowNumber}`;
      sheet.getCell(position).value = ruleSet.ruleSetName;
      this.fontBoldByCells.push(position);
      this.contextAlignmentOfCells.left.push(position);
      position = `F${this.lastRowNumber}`;
      sheet.getCell(position).value = `待修改的缺陷，共${ruleSet.total}个`;
      this.contextAlignmentOfCells.right.push(position);
      this.mergeByCells.push(...[`A${this.lastRowNumber}:B${this.lastRowNumber}`, `F${this.lastRowNumber}:G${this.lastRowNumber}`]);
      const rules = [...ruleSet.rules.level1, ...ruleSet.rules.level2, ...ruleSet.rules.level3];
      ['header', ...rules].forEach((rule, index) => {
        this.lastRowNumber += 1;
        sheet.getRow(this.lastRowNumber).height = 40;
        ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((col) => {
          const position = `${col}${this.lastRowNumber}`;
          this.contextAlignmentOfCells.left.push(position);
          if (rule === 'header') {
            this.fontBoldByCells.push(position);
            this.borderBoldByCells.push(position);
          }
        });
        this.mergeByCells.push(`C${this.lastRowNumber}:E${this.lastRowNumber}`);
        if (rule === 'header') {
          sheet.getCell(`A${this.lastRowNumber}`).value = '序号';
          sheet.getCell(`B${this.lastRowNumber}`).value = ruleSet.ruleSetName;
          sheet.getCell(`C${this.lastRowNumber}`).value = '简述';
          sheet.getCell(`F${this.lastRowNumber}`).value = '缺陷数量';
          sheet.getCell(`G${this.lastRowNumber}`).value = '缺陷等级';
          return;
        }
        sheet.getCell(`A${this.lastRowNumber}`).value = rule.index;
        sheet.getCell(`B${this.lastRowNumber}`).value = rule.ruleCode;
        sheet.getCell(`C${this.lastRowNumber}`).value = rule.name;
        sheet.getCell(`F${this.lastRowNumber}`).value = rule.total;
        sheet.getCell(`G${this.lastRowNumber}`).value = rule.level;
        const fillBgColorPosition = `G${this.lastRowNumber}`;
        switch (rule.lvl) {
          case 1: {
            this.fillBgColorByCells.mandatory.push(fillBgColorPosition);
            break;
          }
          case 2: {
            this.fillBgColorByCells.required.push(fillBgColorPosition);
            break;
          }
          case 3: {
            this.fillBgColorByCells.advisory.push(fillBgColorPosition);
            break;
          }
          default: break;
        }
        if (index === rules.length) {
          ['A', 'B', 'C', 'D', 'E', 'F', 'G'].forEach((key) => {
            this.borderBoldOnlyBottomByCells.push(`${key}${this.lastRowNumber}`);
          });
        }
      });
      this.lastRowNumber += 1;
    });
  }
}
module.exports = SummaryExcel;
